/*
 * bw_Output.cpp
 *
 *  Created on: 2018年11月9日
 *      Author: linsainan
 */

#include "bw_Output.h"
#include "cJSON.h"
#include "bw_FcgiRequest.h"
#include "bw_jskey.h"
#include "bw_slot.h"
#include "bw_public.h"
#include "bw_sys.h"

using namespace bwcgi;

extern char g_outbuf[];

// 输出列表获取
const char* output_list() {
	int boardNum = slot_num();

	cJSON *pout_root = NULL;
	cJSON *p_obj = NULL;
	cJSON *p_arr = NULL;
	cJSON *p_tmp = NULL;
	stENC_OUTSET* out_info = NULL;

	pout_root = cJSON_CreateObject();
	cJSON_AddNumberToObject(pout_root, "retCode", 0);
	cJSON_AddStringToObject(pout_root, "retMsg", "SUCCESS");
	p_obj = cJSON_CreateObject();
	cJSON_AddItemToObject(pout_root, "retData", p_obj);
	p_arr = cJSON_CreateArray();
	cJSON_AddItemToObject(p_obj, "output_list", p_arr);

	// channel output
	int chl_num = boardNum * ENC_MAX_CHL;
	int index = 0;
	char tmpbuf[50] = { '\0' };
	for (int i = 0; i < chl_num; i++) {
		p_tmp = cJSON_CreateObject();
		cJSON_AddItemToArray(p_arr, p_tmp);
		index = i + 1;
		out_info = &(g_encset_mst->enc_output[i]);
		cJSON_AddNumberToObject(p_tmp, "id", index);
		cJSON_AddNumberToObject(p_tmp, "real_id", i);
		cJSON_AddStringToObject(p_tmp, "type", BWENC_OUT_TYPE_SPTS);
		setOutput(p_tmp, out_info, tmpbuf);
		// asi_output
		cJSON_AddNumberToObject(p_tmp, "asi_output", 0);
	}

	// mpts output
	index++;
	p_tmp = cJSON_CreateObject();
	cJSON_AddItemToArray(p_arr, p_tmp);
	cJSON_AddNumberToObject(p_tmp, "id", index);
	cJSON_AddNumberToObject(p_tmp, "real_id", -1);
	cJSON_AddStringToObject(p_tmp, "type", BWENC_OUT_TYPE_MPTS);
	out_info = &(g_encset_mst->enc_mptsout);
	setOutput(p_tmp, out_info, tmpbuf);
	// asi_output
	cJSON_AddNumberToObject(p_tmp, "asi_output", 1);

	char* str = cJSON_PrintUnformatted(pout_root);
	memset(g_outbuf, 0, get_g_oubuf_size());
	memcpy(g_outbuf, str, strlen(str));
	free(str);

	cJSON_Delete(pout_root);
	return g_outbuf;
}

void setOutput(cJSON* p_tmp, stENC_OUTSET* out_info, char* tmpbuf) {
	if (!out_info) {
		cgi_debug("empty out info");
		return;
	}

	// ip
	unsigned int ip = Addr_swap(out_info->out_ethio.ethio_dipaddr);
	sprintf(tmpbuf, "%s", iptostr(ip));
	cJSON_AddStringToObject(p_tmp, "ip", tmpbuf);

	// port
	cJSON_AddNumberToObject(p_tmp, "port", out_info->out_ethio.ethio_dipport);

	// protocol
	cJSON_AddStringToObject(p_tmp, "protocol", "0");

	// code_rate
	cJSON_AddNumberToObject(p_tmp, "code_rate", out_info->out_bitrate_kb);

	// emp_filter
	cJSON_AddNumberToObject(p_tmp, "emp_filter", out_info->out_filte_nullpkt);

	// ip_output
	cJSON_AddNumberToObject(p_tmp, "ip_output", out_info->out_enable_ip);

	// output_state
	cJSON_AddNumberToObject(p_tmp, "output_state", out_info->out_status);

}

// 输出信息编辑
const char* output_edit(const char* json) {
	eENC_ERROR code = BWENC_ERROR_UNKNOW;
	cJSON* root = cJSON_Parse(json);
	if (!root) {
		cgi_debug("error");
		code = BWENC_ERROR_INVALID_PARAM;
		return bwenc_common_ack(code);
	}

	cJSON* param = cJSON_GetObjectItem(root, KEY_PARAM);
	if (!param) {
		cgi_debug("error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}

	// real_id
	cJSON *p_tmp = cJSON_GetObjectItem(param, "real_id");
	if (!p_tmp || p_tmp->valueint < -1 || p_tmp->valueint > ENC_TOTAL_CHLMAX) {
		cgi_debug("real_id error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}
	int real_id = p_tmp->valueint;

	// ip
	p_tmp = cJSON_GetObjectItem(param, "ip");
	if (!p_tmp ||!p_tmp->valuestring||strlen(p_tmp->valuestring) <= 0) {
		cgi_debug("ip error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}
	unsigned int ip = Addr_swap(ipstrtoint(p_tmp->valuestring));

	// port
	p_tmp = cJSON_GetObjectItem(param, "port");
	if (!p_tmp || p_tmp->valueint < 0 || p_tmp->valueint > BWENC_PORT_MAX) {
		cgi_debug("port error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}
	unsigned short port = p_tmp->valueint;
	if (0 == out_ip_repeat(real_id, ip, port)) {
		cgi_debug("ip port repeat,ip:%d,port:%d", ip, port);
		code = BWENC_ERROR_IP_REPEAT;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}

	/*// code_rate
	p_tmp = cJSON_GetObjectItem(param, "code_rate");
	if (!p_tmp || p_tmp->valueint <= 0) {
		cgi_debug("code_rate error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}
	int code_rate = p_tmp->valueint;*/

	// emp_filter
	p_tmp = cJSON_GetObjectItem(param, "emp_filter");
	if (!p_tmp || (p_tmp->valueint != 0 && p_tmp->valueint != 1)) {
		cgi_debug("emp_filter error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}
	int emp_filter = p_tmp->valueint;

	// ip_output
	p_tmp = cJSON_GetObjectItem(param, "ip_output");
	if (!p_tmp || (p_tmp->valueint != 0 && p_tmp->valueint != 1)) {
		cgi_debug("ip_output error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}
	int ip_output = p_tmp->valueint;

	sem_wait(g_shrmsem);
	stENC_OUTSET* out_info = NULL;
	if (real_id == -1) {
		out_info = &(g_encset_mst->enc_mptsout);
	} else {
		out_info = &(g_encset_mst->enc_output[real_id]);
	}
	out_info->out_ethio.ethio_dipaddr = ip;
	out_info->out_ethio.ethio_dipport = port;
	
	//out_info->out_bitrate_kb = code_rate;
	
	out_info->out_filte_nullpkt = emp_filter;
	out_info->out_enable_ip = ip_output;
	g_encset_mst->enc_setvsion++;
	sem_post(g_shrmsem);

	cJSON_Delete(root);
	log_write(BWENC_LOG_SYS_SET,"Output info modified successfully");
	return bwenc_common_ack(BWENC_ERROR_NONE);
}

int out_ip_repeat(int real_id, unsigned int ip, unsigned short port) 
{
	int boardNum = slot_num();
	stENC_OUTSET* out_info = NULL;
	
	// channel output
	int chl_num = boardNum * ENC_MAX_CHL;
	
	for (int i = 0; i < chl_num; i++) 
	{
		out_info = &(g_encset_mst->enc_output[i]);
		if (real_id != i && out_info->out_ethio.ethio_dipaddr == ip
				&& out_info->out_ethio.ethio_dipport == port) {
			return 0;
		}
	}

	// mpts output
	out_info = &(g_encset_mst->enc_mptsout);
	if (real_id != -1 && out_info->out_ethio.ethio_dipaddr == ip
			&& out_info->out_ethio.ethio_dipport == port) {
		return 0;
	}

	return 1;
}
